package com.ice.framework.redission.util;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.ice.framework.common.exception.BusinessException;
import org.apache.poi.ss.formula.functions.T;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * @author wangwei
 * @Date 2022/1/17 09:50
 */
@Configuration
public class RedissionUtil {

    private static Logger logger = LoggerFactory.getLogger(RedissionUtil.class);

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 方法执行，自动加锁释放锁
     * @Author wangwei
     * @Date 2022/1/18
     */
    public T executeLock(String lockKey, Supplier<T> supplier) {
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("");
        readWriteLock.readLock().lock();

        RLock lock = this.lock(lockKey);
        try {
            return supplier.get();
        } catch (Exception e) {
            logger.error("执行异常：{}", ExceptionUtil.stacktraceToString(e));
            throw new BusinessException("异常");
        } finally {
            this.unlock(lock);
        }
    }

    /**
     * 方法执行，自动加锁释放锁
     * @Author wangwei
     * @Date 2022/1/18
     */
    public void executeLock(String lockKey, Consumer<T> consumer) {
        RLock lock = this.lock(lockKey);
        try {
            consumer.accept(null);
        } catch (Exception e) {
            logger.error("执行异常：{}", ExceptionUtil.stacktraceToString(e));
            throw new BusinessException("异常");
        } finally {
            this.unlock(lock);
        }
    }

    /**
     * 获取锁
     * @Author wangwei
     * @Date 2022/1/17
     */
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }

    /**
     * 获取锁
     * @Author wangwei
     * @Date 2022/1/17
     */
    public RLock lock(String lockKey, Long timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, TimeUnit.SECONDS);
        return lock;
    }


    /**
     * 获取锁
     * @Author wangwei
     * @Date 2022/1/17
     * @param lockKey 加锁名称
     * @param timeout 超时时间
     * @param unit 超时单位
     * @return
     */
    public RLock lock(String lockKey, Long timeout, TimeUnit unit) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }

    /**
     * 尝试获取锁
     *
     * @param lockKey
     * @param waitTime  最多等待时间
     * @param leaseTime 上锁后自动释放锁时间
     * @return
     */
    public boolean tryLock(String lockKey, int waitTime, int leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            logger.warn("未获取到锁，key: {}", lockKey);
            return false;
        }
    }

    /**
     * 释放锁
     * @Author wangwei
     * @Date 2022/1/17
     */
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        if (lock.isLocked()) {
            lock.unlock();
        }
    }

    /**
     * 释放锁
     * @Author wangwei
     * @Date 2022/1/17
     */
    public void unlock(RLock lock) {
        if (lock.isLocked()) {
            lock.unlock();
        }
    }


}
